Migración

¿Cómo actualizar tu proyecto a la última versión de OpenXava?

  • Descarga la última distribución de OpenXava y descomprímela en un lugar nuevo.
  • Si tu versión de OpenXava actual es anterior a la 5.0 crea un proyecto Java nuevo llamado Addons en tu workspace usando Eclipse.
  • Para tu Eclipse.
  • Borra los proyectos Addons (a partir de v5.0) y OpenXava de tu workspace.
  • Copia los proyectos Addons y OpenXava desde el workspace del nuevo OpenXava al tuyo.
  • Arranca tu Eclipse.
  • Haz un Build All (Ctrl-B)
  • Ejecuta la tarea ant actualizarOX de tu proyecto.
  • Refresca (con F5) tu proyecto.
  • Revisa las intrucciones que siguen.
  • Si tu aplicación falla:
    • Para el Tomcat y borra las carpetas work y temp (dentro del Eclipse haz un Clean Tomcat Work Directory... en tu servidor en la vista Servers).
    • Quita tu aplicación del Tomcat y vuélvela a añadir.

Para migrar de OpenXava 5.8.1 a OpenXava 5.9

Nuevas acciones en colecciones (para pruebas JUnit)

Las colecciones tienen acciones nuevas disponibles para el usuario (CollectionCopyPaste.cut y CollectionCopyPaste.paste), por tanto si compruebas todas las acciones presentes en tus pruebas junit, necesitarás modificarlas para tener en cuenta la nueva acción CollectionCopyPaste.cut. CollectionCopyPast.paste está oculta por defecto, por lo que podemos ignorarla. Además, List.sumColumn ahora está siempre presente, incluso si la colección está vacía:
String [] acciones = {
    "Navigation.previous",
    "Navigation.first",
    "Navigation.next",
    "CRUD.new",
    "CRUD.save",
    "CRUD.delete",
    "CRUD.refresh",
    "Mode.list",
    "Mode.split",
    "Collection.new",
    "Collection.removeSelected",
    "CollectionCopyPaste.cut", // AÑADE ESTA ENTRADA
    "Print.generatePdf",
    "Print.generateExcel",
    "List.filter",
    "List.orderBy",
    "List.sumColumn", // SIEMPRE PRESENTE, INCLUSO CON LA COLECCIÓN VACÍA
    "List.changeColumnName"
};
assertActions(acciones);

Los booleanos muestran su etiqueta en vez de un icono en las listas

Hasta ahora cuando un booleano era verdadero en la lista, se mostraba un icono de una marca de verificación y si era falso no se mostraba nada. A partir de ahora, si el booleano es verdadero se mostrará su etiqueta, es decir, para una propiedad pagado se mostraría "Pagado". Este cambio no requiere ninguna modificación en el código de tu aplicación, sin embargo es posible que tengas que cambiar alguna prueba JUnit de listas o colecciones. Por ejemplo, si tienes la siguiente línea en tu prueba:
assertValueInList(2, 4, "Yes");
Deberías cambiarla por:
assertValueInList(2, 4, "Pagado");
Si la etiqueta de propiedad es "Pagado".
Y para el caso de falso, deberías cambiar:
assertValueInList(2, 4, "No");
Por:
assertValueInList(2, 4, "");
Por otra parte si quieres mantener el comportamiento clásico, simplemente añade la siguiente entrada a tu fichero editores.xml:
<editor url="booleanEditor.jsp">
  <formateador clase="org.openxava.formatters.BooleanFormatter" >
    <poner propiedad="nullAsFalse" valor="true"/>
  </formateador>
  <formateador-lista clase="org.openxava.formatters.BooleanIconListFormatter" />
  <para-tipo tipo="boolean" />
  <para-tipo tipo="java.lang.Boolean" />
</editor>
Fíjate en el uso de BooleanIconListFormatter como formateador para la lista.

Las páginas de bienvenida y la de inicio de sesión están separadas

Ahora el contenido de welcome.jsp se muestra cuando se va a la raíz de la aplicación. welcome.jsp llena toda la página, por eso deberías modificar tu actual welcome.jsp para incluir <head>, importar los CSSs necesarios e incluir un vínculo a la página de inicio de sesión (m/SignIn). Usa el welcome.jsp incluido por defecto como guía. Usa Addons/web/naviox/welcome.jsp como guía.

Para migrar de OpenXava 5.8 a OpenXava 5.8.1

No hay consideraciones.

Para migrar de OpenXava 5.7.1 a OpenXava 5.8

Nueva acciones en modo lista (para pruebas JUnit)

La lista tiene nuevas acciones disponibles (List.changeColumnName y ImportData.importData), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta las nuevas acciones "List.changeColumnName" e "ImportData.importData":
private String [] accionesLista = {
    "Print.generatePdf",
    "Print.generateExcel",
    "ExtendedPrint.myReports",
    "CRUD.new",
    "CRUD.deleteSelected",
    "CRUD.deleteRow",
    "Mode.detailAndFirst",
    "Mode.split",
    "List.filter",
    "List.orderBy",
    "List.viewDetail",
    "List.hideRows",
    "List.sumColumn",
    "List.changeConfiguration",
    "ListFormat.select",
    "List.changeColumnName", // AÑADE ESTA ENTRADA
    "ImportData.importData"  // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

La acción de borrar no está disponible mientra se está creando un nuevo elemento (para pruebas JUnit)

En v5.8 cuando el usuario pulsa en Nuevo la acción Borrar se oculta. Esto no afecta el código de tu aplicación pero si usas assertActions() en tu pruebas puede que tengas que adaptarlas:
String [] accionesDespuesNuevo = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 // "CRUD.delete", // QUITA ESTA LÍNEA
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
 "List.filter",
 "List.orderBy",
 "Print.generatePdf",
 "Print.generateExcel"
};
assertActions(accionesDespuesNuevo);

Acción de buscar ya no está disponible en modo detalle (para pruebas JUnit)

Si usas assertActions() en tus pruebas deberías adaptarlas:
String [] acciones = {
 "Navigation.previous",
 "Navigation.first",
 "Navigation.next",
 "CRUD.new",
 "CRUD.save",
 "CRUD.delete",
 // "CRUD.search", // QUITA ESTA LÍNEA
 "CRUD.refresh",
 "Mode.list",
 "Mode.split",
};
assertActions(acciones);
Si usas CRUD.search en tus pruebas las puedes cambiar por CRUD.refresh, es decir cambia:
execute("CRUD.search");
setValue("numero", "123");
execute("Search.search");
Por:
setValue("numero", "123");
execute("Search.search");
Además, si quieres que la acción de buscar vuelva puedes usar el nuevo controlador SearchForCRUD que contiene únicamente la acción de buscar. Para definir un módulo con la acción buscar en aplicacion.xml añade el controlador SearchForCRUD:
<modulo nombre="Albaran">
    <modelo nombre="Albaran"/>
    <controlador nombre="Typical"/>
    <controlador nombre="SearchForCRUD"/> <!-- AÑADE ESTA LÍNEA -->
</modulo>
Otra opción es definirlo en controladores.xml de esta manera:
<controlador nombre="Autor">
    <hereda-de controlador="Typical"/>
    <hereda-de controlador="SearchForCRUD"/> <!-- AÑADE ESTA LÍNEA  -->
    <accion nombre="hazAlgo"
        clase="com.miempresa.prueba.acciones.HazAlgo" />
</controlador>
Incluso si vuelves a añadir la acción de buscar con SearchForCRUD has de modificar tus prueba JUnit porque search ya no está en CRUD sino en SearchForCRUD. Por lo tanto has de cambiar:
execute("CRUD.search");
Por:
execute("SearchForCRUD.search");
También tenemos un controlador TypicalWithSearch que tiene todas las acciones de Typical más la acción de buscar, igual que con el Typical de toda la vida. Si quieres que se use por defecto escribe el siguiente código al principio de tu aplicacion.xml:
<modulo-defecto>
    <controlador nombre="TypicalWithSearch"/>
</modulo-defecto>

Módulos sin filas empiezan ejecutando la acción nuevo (para pruebas JUnit)

Deberías tocar las pruebas JUnit con módulos sin filas, porque ahora empiezan en modo detalle. Por ejemplo, deberías cambiar un código como este:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  assertListRowCount(0); // AHORA ESTA LÍNEA FALLA
  execute("CRUD.new");
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}
Si el módulo no tiene filas, ahora empieza en modo detalle por tanto la primera línea fallará. Podemos cambiar a modo lista al principio:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  execute("Mode.list"); // AÑADE ESTA LÍNEA
  assertListRowCount(0);
  execute("CRUD.new");
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}
O si tu prueba va directamente al modo detalle, como en este ejemplo, simplemente quita la primera parte de la prueba:
public void testCrearExamenConAlMenosUnaPregunta() throws Exception {
  // assertListRowCount(0); // QUITA ESTA LÍNEA
  // execute("CRUD.new"); // QUITA ESTA LÍNEA
  setValue("nombre", "ADMISIÓN");
  execute("CRUD.save");
  ...
}

Para migrar de OpenXava 5.7 a OpenXava 5.7.1

No hay consideraciones.

Para migrar de OpenXava 5.6.1 a OpenXava 5.7

Acción List.changeConfigurationName renombrada como List.changeConfiguration (para pruebas JUnit)

La acción de lista List.changeConfigurationName ahora es List.changeConfiguration, por tanto si compruebas todas las acciones presentes en tus pruebas JUnit, has de modificar el nombre de esta acción:
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  // "List.changeConfigurationName" // QUITA ESTA ENTRADA
  "List.changeConfiguration" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Propiedades por defecto mejoradas para lista y colecciones (para pruebas JUnit)

Hasta ahora cuando @Tab para la lista, o @ListProperties para las colecciones, se omite por defecto OpenXava muestra todas las propiedades planas de la entidad. A partir de v5.7 cuando @Tab/@ListProperties no está presente las propiedades a mostrar son las planas, los ids de las referencias, el nombre, descripción o título de las referencias o si no está presente la primera propiedad no id de la referencia. Además, las propiedades planas que son oids se excluyen.
Por ejemplo, si tenemos esta clase sin @Tab:
@Entity
public class Factura {
 private int ano;
 private int numero;
 private Date fecha;
 @ManyToOne
 private Cliente cliente;
 
 @Stereotype("ARCHIVOS") @Column(length=32)
 private String archivos;
 
 ...
}
En versiones anteriores hubiéramos obtenido: ano, numero, fecha, archivos
En v5.7 obtenemos: ano, numero, fecha, cliente.numero, cliente.nombre
Si tienes pruebas JUnit contra entidades sin @Tab puede que tengas que adaptarlas.

@NewAction ya no sirve para definir la acción de añadir en las colecciones @OneToMany convencionales

Desde v5.7 las colecciones @OneToMany sin cascade REMOVE tienen disponible a la vez la acción 'Nuevo' para crear nuevos elementos y la acción 'Añadir' para añadir elementos escogiendo entre los ya existentes. Antes de v5.7 solo la acción 'Añadir' estaba disponible y podía definirse con @NewAction. Ahora tenemos una nueva anotación, @AddAction, para la acción 'Añadir' y usamos la vieja @NewAction solo para la acción 'Nuevo'.
Deberías cambiar @NewAction por @AddAction en la colecciones sin cascade REMOVE. Cambia:
@NewAction("Factura.anadirAlbaranes")
@OneToMany(mappedBy="factura")
private Collection<Albaran> albaranes;
Por:
@AddAction("Factura.anadirAlbaranes")
@OneToMany(mappedBy="factura")
private Collection<Albaran> albaranes;

Colecciones de entidades sin REMOVE cascade permiten editar los elementos (para pruebas JUnit)

No necesitas cambiar tu código de aplicación, simplemente adaptar tus pruebas JUnit cambiando:
execute("Collection.view", "row=1,viewObject=xava_view_customers");
Por:
execute("Collection.edit", "row=1,viewObject=xava_view_customers");
Fíjate que ahora no es "Collection.view" sino "Collection.edit".

Optimizadas las etiquetas automáticas para las referencias en la lista (para pruebas JUnit)

Cuando en un lista tenemos un propiedad de una referencia y la propiedad se llama "nombre", "descripcion" o "titulo", el nombre de la propiedad se omite, simplemente se usa el nombre de la referencia. Es decir, en lugar de "Nombre de Cliente" ahora es solamente "Cliente". Esto no afecta al código de tu aplicación en absoluto, pero si verificas las etiquetas de alguna lista en tus pruebas JUnit, deberás de adaptarlo.
Cambia esto:
assertLabelInList(4, "Nombre de Cliente");
Por esto:
assertLabelInList(4, "Cliente");

Para migrar de OpenXava 5.6 a OpenXava 5.6.1

No hay consideraciones.

Para migrar de OpenXava 5.5.1 a OpenXava 5.6

La acción ExtendedPrint.myReports ya no está disponible por defecto (para pruebas JUnit)

Por lo tanto compruebas todas las acciones presentes en tu prueba JUnit, tendrás que modificarlo eliminando ExtendedPrint.myReports de la lista:
private String [] accionesLista = {
    "Print.generatePdf",
    "Print.generateExcel",
    // ELIMINA ESTA LÍNEA "ExtendedPrint.myReports",
    "CRUD.new",
    "CRUD.deleteSelected",
    ...
};
assertActions(accionesLista);
Aunque la acción no esté disponible por defecto, todavía existe en OpenXava y funciona perfectamente. De hecho, hay un nuevo controlador TypicalExtendedPrint para facilitar su uso. Si quieres continuar usando la funcionalidad Mis informes cambia Typical por TypicalExtendedPrint en tu aplicacion.xml y controladores.xml, incluso lo puedes declarar como controlador por defecto.

Nueva acción en lista (para pruebas junit)

La lista tiene una nueva acción disponible (List.changeConfigurationName), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta la nueva acción "List.changeConfigurationName":
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn",
  "List.changeConfigurationName" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Para migrar de OpenXava 5.5 a OpenXava 5.5.1

Necesario llamar a super dentro de setUp() de las pruebas antes de usar JPA

A partir de v5.5.1 la inicialización de JPA en las pruebas ModuleTestBase se hace en el método setUp(), por lo que si usas JPA dentro de un método setUp() has de llamar a super antes. Es decir, si tienes un código como este en tu prueba:
protected void setUp() throws Exception {
    crearEntidadesUsandoJPA(); // Ahora falla, porque JPA todavía no está inicializado
    super.setUp();
}
Cámbialo por:
protected void setUp() throws Exception {
    super.setUp(); // JPA se incializa aquí
    crearEntidadesUsandoJPA();
}

Para migrar de OpenXava 5.4.1 a OpenXava 5.5

Los combos para @DescriptionsList ya no son selects de HTML (sólo si usas el API de HtmlUnit)

Los combos para @DescriptionsList ahora se crean usando un input text de HTML más algo de código JavaScript y CSS para simular un combo. Esto no requiere ningún cambio en el código de tu aplicación, ni siquiera has de cambiar el código de tus pruebas jUnit si sólo usas los métodos de ModuleTestBase. Sin embargo, si usas el API de HtmlUnit directamente, por ejemplo con getHtmlPage() o getWebClient() en tus pruebas, y manejas un combo de un @DescriptionList. En ese caso tienes que adaptar tu código, cambiando:
form.getSelectByName("ox_MiAp_MiModulo__miReferencia___id").setSelectedAttribute("ElValor", true);
Por:
HtmlInput comboInput = form.getInputByName("ox_MiAp_MiModulo__miReferencia___id");
comboInput.setValueAttribute("ElValor");
((HtmlInput) comboInput.getPreviousElementSibling()).setValueAttribute("Algo"); // Un truco para evitar que JavaScript borre el valor real
((HtmlInput) comboInput.getNextElementSibling()).setValueAttribute("Algo"); // Un truco para evitar que JavaScript borre el valor real

Para migrar de OpenXava 5.4 a OpenXava 5.4.1

No hay consideraciones.

Para migrar de OpenXava 5.3.2 a OpenXava 5.4

Iconos en lugar de imágenes para las acciones

A partir de v5.4 las acciones estándar de OpenXava usan iconos de Material Design Icons en vez de imágenes gif o png. El atributo imagen de <accion/> en controllers.xml continúa funcionando como siempre, sin embargo tenemos un nuevo atributo icono que es el que se usa en las acciones estándar. El efecto es que en tu aplicación todas las acciones estándar usaran los nuevos iconos monocromo y tus acciones propias usarán las vieja acciones en color con imágenes gif y png. Esto podría quedar un poco feo, para arreglarlo cambia imagen por icono en tus acciones. Por ejemplo, cambia:
<accion nombre="borrar" modo="detalle" confirmar="true"
    clase="com.miempresa.miaplicacion.acciones.MiBorrar"
    imagen="delete.gif"
    atajo-de-teclado="Control D"/>
Por esto:
<accion nombre="borrar" mode="detalle" confirmar="true"
    clase="com.miempresa.miaplicacion.acciones.MiBorrar"
    icono="delete"
    atajo-de-teclado="Control D"/>
Para ver todos los iconos disponibles visita Material Design Icons.
Por otra parte, si prefieres seguir con los viejos iconos de toda la vida, simplemente añade la siguiente línea en xava.properties:
useIconsInsteadOfImages=false
De esta manera todas las acciones, incluyendo las estándar, usarán las viejas imágenes en color.

Para migrar de OpenXava 5.3.1 a OpenXava 5.3.2

No hay consideraciones.

Para migrar de OpenXava 5.3 a OpenXava 5.3.1

El jar de HSQLDB se ha movido desde OpenXavaTest a OpenXava

Si referencias a este jar tendrás que cambiar la ruta. Por ejemplo, si utilizas HSQLDB en alguno de tus proyectos, deberías cambiar en la tarea Ant actualizarEsquema de build.xml esto:
<property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
Por esto:
<property name="schema.path" value="../OpenXava/lib/hsqldb.jar"/>

Para migrar de OpenXava 5.2.1 a OpenXava 5.3

Hibernate actualizado a 4.3

Si usas la API de JPA o haces un uso básico de la API de Hibernate no tendrás que cambiar nada. Ahora bien, si usas características avanzadas de Hibernate seguramente esta actualización te afecte.
Por ejemplo, si tienes tu propios tipos de Hibernate (UserType) has de cambiar en tu definición de tipo lo siguiente:
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
Por:
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor sessionImplementor, Object owner) throws HibernateException, SQLException {
Y esto:
public void nullSafeSet(PreparedStatement ps, Object value, int index) throws HibernateException, SQLException {
Por:
public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor sessionImplementor) throws HibernateException, SQLException {
Por supuesto, si llamas a estos métodos debes de adaptar la llamada. Por ejemplo, un código como este:
((UserType) hibernateType).nullSafeSet(ps, o, 1);
Se quedaría:
((UserType) hibernateType).nullSafeSet(ps, o, 1, null);
Fíjate en que enviar un nulo para el nuevo parámetro es suficiente.
Además, en lugar de Hibernate.INTEGER has de usar IntegerType.INSTANCE.
La forma de registrar los eventos ha cambiado, esto te afecta sólo si usas componentes XML con el API de JPA, en cuyo caso has de quitar el registro de eventos de tu persistence.xml, como sigue:
<persistence-unit name="default" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
 
    <properties>
        <property name="hibernate.ejb.cfgfile" value="/hibernate-jpa.cfg.xml"/>
        <!-- ELIMINA LAS SIGUIENTES LÍNEAS
        <property name="hibernate.ejb.event.pre-insert" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener, org.openxava.hibernate.impl.DefaultValueCalculatorsListener"/>
        <property name="hibernate.ejb.event.pre-update" value="org.openxava.hibernate.impl.CalculatorsListener, org.openxava.hibernate.impl.ReferenceConverterToDBListener"/>
        <property name="hibernate.ejb.event.pre-delete" value="org.openxava.hibernate.impl.CalculatorsListener"/>
        <property name="hibernate.ejb.event.post-load" value="org.openxava.hibernate.impl.CalculatorsListener"/>
        -->
    </properties>
</persistence-unit>
También si usas componentes XML ya no puedes tener una referencia usada como clave si el valor no existe en la tabla referenciada. Este caso ya no está permitido por Hibernate. Este caso nunca ha estado permitido en JPA. Deberías de pensar en una forma diferente de resolver el problema, como añadiendo una clave autogenerada o creando el registro en la tabla referenciada.
Con Hibernate 4.3 la forma por defecto de liberar una conexión ha cambiado, por lo que te podrías encontrar un "Could not open connection error". Para evitarlo añade la siguiente línea a tu persistence.xml:
<persistence-unit name="default">
    ...
    <properties>
        ...
        <!-- Añade la siguiente línea -->
        <property name="hibernate.connection.release_mode" value="after_transaction"/>
 
    </properties>
 
</persistence-unit>

Hibernate Validator 3 quitado de la distribución

Hasta ahora hemos incluido ambos, el antiguo Hibernate Validator 3 y la última versión de Hibernate Validator, en OpenXava para conseguir la máxima compatibilidad del código antiguo. Por desgracia, Hibernate 4.3 no soporta Hibernate Validator 3, por eso hemos tenido que quitarlo de OpenXava.
Si simplemente usas anotaciones de validación como @Max, @Length, @Size, etc. es suficiente con cambiar los imports, cambia:
import org.hibernate.validator.*;
Por:
import javax.validation.constraints.*;
import org.hibernate.validator.constraints.*;
En el caso de @Digits aparte de cambiar los susodichos imports tienes que cambiar los nombres de los parámetros, cambiando esto:
@Digits(integerDigits=10, fractionalDigits=6)
Por esto:
@Digits(integer=10, fraction=6)
Ya no puedes usar InvalidStateException de Hibernate Validator 3. Por lo tanto, si la usas para lanzar un error de validación desde tu entidad u acción tendrás que cambiarla por otra excepción. Por ejemplo, un código como el siguiente:
@PreRemove
public void validarAlBorrar() {
    if (numero == 1) {
        throw new InvalidStateException(
            new InvalidValue [] {
                new InvalidValue(
                    "uno_no_se_puede_borrar", getClass(), "numero",
                    getNumero(), this)
            }
        );
    }
}
Ahora podría escribirse de esta manera:
@PreRemove
public void validarAlBorrar() {
    if (numero == 1) {
        throw new javax.validation.ValidationException("uno_no_se_puede_borrar");
    }
}
Si has definido tu propio validador con el Hibernate Validator antiguo deberías reescribirlo usando el estándar Bean Validation. No te preocupes, la conversión es muy sencilla. En tu anotación cambia @ValidatorClass por @Constraint y añade groups() y payload(), así:
@Constraint(validatedBy = MyValidator.class) // En lugar de @ValidatorClass(PropertyValidatorValidator.class)
public @interface MyAnnotation {
 
    ...
 
    // Añade el siguiente código
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
 
}
Y en tu clase validador, cambia esto:
public class RequiredValidator implements Validator<Required> {
Por:
public class RequiredValidator implements ConstraintValidator<Required, Object> {
Y esto:
public boolean isValid(Object value) {
Por:
public boolean isValid(Object value, ConstraintValidatorContext context) {
Puedes dejar el resto del código como está.

@Required, @PropertyValidator y @EntityValidator son restricciones de Bean Validation

Antes eran restricciones de Hibernate Validator 3. Si haces tu propio commit y tratas de capturar la excepción de validación has de cambiar la excepción a atrapar. Si tienes un código como este:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof InvalidStateException) {
        InvalidStateException iex = (InvalidStateException) ex.getCause();
        int cantidadValoresInvalidos = iex.getInvalidValues().length;
        String propiedad = iex.getInvalidValues()[0].getPropertyName();
        String mensaje = iex.getInvalidValues()[0].getMessage();
        ...
    }
}
Deberías escribirlo de esta manera:
try {
    XPersistence.commit();
}
catch (RollbackException ex) {
    if (ex.getCause() instanceof ConstraintViolationException) {
        ConstraintViolationException cex = (ConstraintViolationException) ex.getCause();
        int cantidadValoresValidos = cex.getConstraintViolations().size();
        ConstraintViolation v = cex.getConstraintViolations().iterator().next();
        String propiedad = v.getPropertyPath().toString());
        String mensaje = v.getMessage());
        ...
    }
}

Prefijo para JNDI en Tomcats antiguos

Hibernate 4.3 usa una forma diferente de buscar los recursos JNDI que funciona bien con Tomcat 7.0.27 (y superior) y Tomcat 6.0.36 (y superior) pero falla con versiones anteriores. Esto no es un bug de Hibernate sino un bug del Tomcat. Por suerte, hay un truco para hacer que el nuevo Hibernate funcione incluso con las versiones antiguas de Tomcat, simplemente añade un // al nombre JNDI. Es decir, si estás usando una versión de Tomcat anterior a 7.0.27 o 6.0.36 cambia en tu persistence.xml esto:
<non-jta-data-source>java:comp/env/jdbc/TuAplicacionDS</non-jta-data-source>
Por esto:
<non-jta-data-source>java://comp/env/jdbc/TuAplicacionDS</non-jta-data-source>
Y en hibernate.cfg.xml cambia esto:
<property name="hibernate.connection.datasource">java:comp/env/jdbc/TuAplicacionDS</property>
Por esto otro:
<property name="hibernate.connection.datasource">java://comp/env/jdbc/TuAplicacionDS</property>
Fíjate en // antes de comp. Si usas nombres JNDI en otras partes de tu aplicación también tendrías que cambiarlos. Lo bueno es que las nuevas versiones de Tomcat también funcionan de esta forma, por tanto si usas siempre esta notación tu aplicación funcionará en cualquier Tomcat.

Actualización de librerias EL para Tomcat 6

Si usas Tomcat 6 copia el-api.jar y jasper-el.jar de la carpeta lib del Tomcat incluido en OpenXava (o cualquier Tomcat 7) a la carpeta lib de tu Tomcat 6. Esto es requerido por última versión de Hibernate Validator.

Librería Automated Business Logic (ABL) quitada de la distribución

Por desgracia, ABL no soporta Hibernate 4.3. Además, ABL ha sido descontinuada desde 2012, por tanto tampoco soportará Hibernate 4.3 en el futuro. Por lo tanto, no tenemos otra opción que quitar ABL de la distribución de OpenXava. Por suerte, mover la lógica en las anotaciones ABL a código Java es fácil. Por ejemplo, si tienes una clase de lógica ABL como esta:
public class PedidoLogic {
 
    @Formula("precioProducto * cantidad")
    public void deriveImporte() { }
 
}
Borra la clase de arriba y mueve el cálculo en la anotación @Formula a un método @PrePersist y @PreUpdate en la entidad. Así:
@Entity
public class Pedido {
 
    ...
 
    @PrePersist @PreUpdate
    private void deriveImporte() {
        importe = new BigDecimal(cantidad).multiply(precioProducto);
    }
}
Además, has de eliminar la siguiente entrada de tu persistence.xml:
<property name="hibernate.current_session_context_class"
    value="com.autobizlogic.abl.session.LogicThreadLocalSessionContext"/>

schema.path necesario en tarea ant generarEsquema

Esto afecta a generarEsquema no a actualizarEsquema. Si tienes una tarea generarEsquema en tu build.xml, añade schema.path, como sigue:
<!-- Genera el esquema desde cero. Lo muestra en consola, pero no lo ejecuta -->
<target name="generarSchema">
 
    <ant antfile="../OpenXava/build.xml" target="generateSchemaJPA">
        <property name="persistence.unit" value="junit"/>
        <!-- AÑADE LA SIGUIENTE LÍNEA PARA v5.3 -->
        <property name="schema.path" value="../OpenXavaTest/lib/hsqldb.jar"/>
    </ant>
 
</target>

Para migrar de OpenXava 5.2 a OpenXava 5.2.1

Entidad obtenida de la vista tiene nulos para referencias inexistentes

Hasta v5.2 todas las referencias de una entidad obtenida vía getView().getEntity() tenían valor, incluso si las referencias no existían. Esto producía un error muy feo porque JPA trataba de grabar los objetos transitorios como referencias. A partir de v5.2.1, las referencias vacías son nulo, esto es más natural (funciona como cuando obtenemos los objetos de la base de datos) y resuelve el susodicho error.
Si tienes código que confía en este comportamiento tienes que cambiarlo. Es decir, has de hacer cambios como este:
Factura factura = (Factura) getView().getEntity();
if (factura.getCliente().getCodigo() == 0) { // En v5.2 si cliente está vacío se devuelve un cliente vacío
Por:
Factura factura = (Factura) getView().getEntity();
if (factura.getCliente() == null) { // En v5.2.1 si cliente está vacío se devuelve nulo

Para migrar de OpenXava 5.1.x a OpenXava 5.2

HtmlUnit actualizado a 2.15

Si usas HtmlUnit directamente en tus pruebas jUnit por medio de getHtmlPage() o getWebClient() deberías adaptar tu código a la nueva API de HtmlUnit. Por ejemplo, deberías cambiar:
getWebClient().setCssEnabled(true);
Por:
getWebClient().getOptions().setCssEnabled(true);
Y:
HtmlElement consola = getHtmlPage().getElementById("xava_console");
Por:
HtmlElement consola = getHtmlPage().getHtmlElementById("xava_console");
Y muchas más cosas. Por desgracia, el equipo de HtmlUnit refactoriza su librería en cada nueva versión menor, por tanto HtmlUnit nunca es compatible hacia atrás.

Para migrar de OpenXava 5.0.x a OpenXava 5.1

@DefaultValueCalculator dependiente de otras propiedades cambia su comportamiento

Si tienes un calculador por defecto como este:
@DefaultValueCalculator(
    value=CalculadorPrecioUnitario.class,
    properties=@PropertyValue(
        name="numeroProducto",
        from="producto.numero")
)
private BigDecimal precioUnitario;
Con versiones anteriores a 5.1 cuando producto.numero cambia precioUnitario se recalcula solo si no tiene valor todavía. Desde la versión 5.1 precioUnitario se recalcula siempre que producto.numero cambia.
Este nuevo comportamiento es más natural, por tanto si no cambias nada tus usuarios tendrán una aplicación que funciona mejor. De todas formas, puede ser que quieras que el valor se recalcule sólo la primera vez, como antes. En ese caso deberías reescribir tu lógica usando @OnChage, es decir, deberías cambiar el código de arriba por este:
@OnChange(RecalcularPreciOUnitarioAlCambiarProducto.class)
private Producto producto;
 
private BigDecimal precioUnitario;

Para migrar de OpenXava 4.9.1 a OpenXava 5.0

La identifación de usuarios afecta a tus pruebas jUnit

Ahora es obligatorio que el usuario se identifique antes de ejecutar un módulo, por tanto tus actuales pruebas jUnit fallarán. Para resolver esto desactiva el mecanismo de identificación de usuarios añadiendo las siguientes entradas al archivo naviox.properties en properties folder:
autologinUser=admin
autologinPassword=admin
De esta manera tus pruebas funcionarán bien sin necesidad de recodificarlas.
Otra opción es dejar el mecanismo de identificación activo y añadir la lógica de identificación en tu código de pruebas:
public void testMiPrueba() throws Exception {
    login("admin", "admin");
    ...
}

Ejecutar los módulos en solitario ya no está disponible por defecto

Cuando vas a /MiAplicacion/modules/MiModule con tu navegador, el modulo se muestra con menus e identificación de usuarios incluidos. Esto no es un problema en absoluto, porque los menús son muy ligeros y la identificación de usuario puede desactivarse con autologinUser y autologinPassword en naviox.properties. Además, dentro de Liferay los módulos funcionan como siempre.
Pero si por alguna razón prefieres trabajar de la forma antigua puedes desactivar la identificación de usuarios y los menús y usar el viejo estilo visual para tus módulos en OpenXava 5. Para hacerlo edita el archivo web.xml del proyecto OpenXava y quita:
<filter>
    <filter-name>naviox</filter-name>
    <filter-class>com.openxava.naviox.web.NaviOXFilter</filter-class>
</filter>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <servlet-name>naviox</servlet-name>
</filter-mapping>
 
<filter-mapping>
    <filter-name>naviox</filter-name>
    <servlet-name>module</servlet-name>
</filter-mapping>
Además cambia:
<servlet>
    <servlet-name>naviox</servlet-name>
    <servlet-class>com.openxava.naviox.web.NaviOXServlet</servlet-class>
</servlet>
Por:
<servlet>
    <servlet-name>modules</servlet-name>
    <servlet-class>org.openxava.web.servlets.ModuleServlet</servlet-class>
</servlet>
Y cambia:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
Por:
<servlet-mapping>
    <servlet-name>modules</servlet-name>
    <url-pattern>/modules/*</url-pattern>
</servlet-mapping>
Finalmente quita:
<servlet-mapping>
    <servlet-name>naviox</servlet-name>
    <url-pattern>/m/*</url-pattern>
</servlet-mapping>
Con estos cambios en OpenXava/web.xml has eliminado los menús y la identificación de usuarios. Tienes que ejecutar la tarea ant actualizarOX para actualizar el web.xml en tu proyecto.
Para usar el estilo visual de OpenXava 4 añade las siguientes entradas a xava.properties de tu proyecto:
styleClass=org.openxava.web.style.Liferay51Style
styleCSS=liferay51/css/everything_unpacked.css

El estilo nativo de iPad no se usa por defecto

Cuando accedes a una aplicación OpenXava 5 desde un iPad el estilo es el mismo que en un navegador de escritorio, el estilo iPad no se muestra por defecto. Esto es así porque el estilo iPad sólo funciona en módulos en solitario, que OpenXava 5 no usa por defecto. Si quieres usar el estilo nativo de iPad sigue las instrucciones de arriba en la sección Ejecutar los módulos en solitario ya no está disponible por defecto para activar lo módulos en solitario.
Sobre el soporte de iPad y tabletas vamos a tener un único estilo que funcione bien para escritorio y tabletas, un estilo adaptable (responsive).

Las clases transitorias requieren un declaración expicita de módulo

Por ejemplo, si tienes una clase transitoria llamada FiltroPorMes con un controlador llamado FiltroPorMes y pruebas la URL /MiAplicacion/modules/FiltroPorMes, no funcionará hasta que declares el módulo en aplicacion.xml como sigue:
<modulo nombre="FiltroPorMes">
    <modelo nombre="FiltroPorMes"/>
    <controlador nombre="FiltroPorMes"/>
</modulo>
De todas formas, siempre ha sido necesario declarar los módulos para las clases transitorias si queriamos generar portlets, por lo tanto si trabajas con portales ya tendrás los módulos definidos.

Nivel de log FINEST genera un montón de traza

Hasta ahora el nivel de log FINEST producía poca traza, pero a partir de v5.0 OpenXava genera abundante traza con FINEST. Por tanto has de editar tu archivo xava.properties y cambiar:
javaLoggingLevel=FINEST
Por:
javaLoggingLevel=FINE
Si quieres mantener una cantidad de traza moderada.
Hasta v4.9.1 los proyectos OpenXava creados con OpenXavaPlantilla tenían FINEST configurado por defecto, a partir de v5.0 tienen FINE.

Eliminada clase Objects de org.openxava.util

Esta clase entra en conflicto con la clase java.util.Objects de Java 7. En lugar de calificar la clase en todos sitios preferimos renombrarla a XObjects. En tu código has de reemplazar Objects por XObjects, como sigue:
Objects.execute(miObjeto, "hacerAlgo");
Ahora tienes que escribir en su lugar:
XObjects.execute(miObjeto, "hacerAlgo");

AccessTracking quitado de la distribución

Puedes continuar usando AccessTracking sin ningún problema, simplemente ejecuta la tarea ant updateOX de AccessTracking después de ejecutar OpenXava.

La URL usada por ModuleTestBase incluye un parámetro por defecto

Esto sólo te afecta si sobrescribes getModuleURL() para añadir parámetros. En este caso simplemente cambia ? por &:
public class MiModuloTest extends ModuleTestBase {
 
    ...
 
    @Override
    protected String getModuleURL() {
        // return super.getModuleURL() + "?miParametro=5"; // Con ? en v4.x.x
        return super.getModuleURL() + "&miParametro=5"; // Con & en v5.0
    }
}

@Digits anula la escala por defecto

Cuando @Digits se especifica la escala por defecto se ignora, incluso si la fracción no se especifica. Es decir, si escribes:
@Digits(integer=10)
private BigDecimal importe;
Con v4.x tiene 2 cifras decimales porque la escala por defecto para BigDecimal es 2. Sin embargo, a partir de v5.0 tiene 0 cifras decimales, porque no especificar fracción es lo mismo que poner fraction=0. Esto te permite tener números BigDecimal con 0 para la parte decimal, pero podría hacer que algunas de tus actuales propiedes numéricas dejen de usar 2 dígitos para la fracción. Para arreglarlo simplemente especifíca la fracción explicitamente, así:
@Digits(integer=10, fraction=2)
private BigDecimal importe;

Formateo de BigDecimal arreglado (para pruebas jUnit)

La escala definida en default-size.xml, en @Column y @Digits se ignoraba al formatear. Lo hemos arreglado. Sí, el formateo de los número funciona mejor, pero tienes que adaptar tus pruebas. Por ejemplo, si usas BigDecimal sin anotaciones deberías cambiar:
assertValue("miNumeroBigDecimal", "20");
por esto:
assertValue("miNumeroBigDecimal", "20.00");

Para migrar de OpenXava 4.9 a OpenXava 4.9.1

Modificador de acceso del método getFrame() cambiado

El modificador de acceso del método getFrame() de org.openxava.web.style.Style fue cambiado de protected a public. Las clases que sobrescriben el método getFrame() requieren que se les cambien el modificador de acceso de protected a public.

Para migrar de OpenXava 4.8.1 a OpenXava 4.9

Cabeceras de informes PDF pueden ocupar varias líneas

Esto no afecta al codigo de tu aplicación en absoluto. Sin embargo, si verificas el contenido del PDF en tus pruebas automáticas quizás necesites hacer algunos ajustes. Por ejemplo, el siguiente código fallaría si la cabecera del informe ahora usará 2 líneas en vez de 1.:
assertPopupPDFLinesCount(5); // Quizás ahora hay 6 líneas, porque la cabecera usa 2 líneas

Controlador CustomReport renombrado a MyReport

Es poco probable que tengas que cambiar tu código, porque este controlador es para uso interno del diálogo 'Mis informes' y sólo está disponible desde OpenXava 4.6. Sin embargo, si has usado acciones del controlador CustomReport en tus pruebas jUnit has de renombrarlas a MyReport.

Para migrar de OpenXava 4.8 a OpenXava 4.8.1

Ocultar un miembro cuyo nombre es el mismo que la sección que lo contiene

Hemos arreglado View.setHidden() para que funcione con secciones también, ya funcionaba con grupos pero no con secciones. Por lo tanto, si tienes una vista como esta:
@View(members=
  ...
  "observaciones { consejo, atajo; observaciones }"
  ...
)
Donde la propiedad observaciones está dentro de una sección llamada observaciones. Hasta ahora si escribías esto:
getView().setHidden("observaciones", true);
Ocultabas la propiedad observaciones, sin embargo desde OpenXava 4.8.1 ocultarás la sección observaciones. En este caso, si aún quieres ocultar la propiedad en lugar de la sección deberías renombrar la sección, como sigue:
@View(members=
   ...
   "comentarios { consejo, atajo; observaciones }"
   ...
)

Para migrar de OpenXava 4.7.1 a OpenXava 4.8

Sin consideraciones.

Para migrar de OpenXava 4.7 a OpenXava 4.7.1

La acción Gallery.return ha sido renombrada como Gallery.close

Esto es porque ahora el editor Gallery usa un diálogo en vez de una vista plana. Además, el controlador para Gallery de solo lectura es Close en vez de Return. Es poco probable que tengas que tocar tu código por estos cambios. Sin embargo, si la has usado en pruebas jUnit tendrás que renombrarla.

Para migrar de OpenXava 4.6.1 a OpenXava 4.7

La acción ExtendedPrint.customReport ha sido renombrada como ExtendedPrint.myReports

Es poco probable que tengas que tocar tu código por este cambio, porque esta es una acción de Typical (por tanto siempre presente) y disponible sólo desde OpenXava 4.6. Sin embargo, si la has usado en pruebas jUnit, @Action o IChainAction, tendrás que renombrarla.

El método getSelected() de Tab y TabBaseAction obsoleto, ahora usamos getSelectedKeys()

El método getSelected() incluido en Tab y TabBaseAction ha sido marcado como obsoleto (deprecated) en sustitución tenemos disponible el método getSelectedKeys() que nos devuelve las claves (Map) de los elementos que se hayan seleccionado.
En la mayoría de casos getSelected() devolverá correctamente las filas que se han seleccionado, pero en el caso de tener alguna fila seleccionada fuera del rango de páginas cargadas no lo hará. Esto ocurrirá por ejemplo si seleccionamos una fila y después ordenamos por algún campo y esta fila queda fuera del rango de páginas cargadas, getSelected() no devolverá esta fila getSelectedKeys() sí.
En nuestro código cambiaremos:
int[] selected = tab.getSelected();
for (int i = 0; i < selected.length; i++){
     Map clave = (Map) tab.getTableModel().getObjectAt(selected[i]);
     ....
}
por
Map[] selected = tab.getSelectedKeys();
for (int i = 0; i < selected.length; i++){
     Map clave = selected[i];
     ....
}

Suprimido método deselectVisualizedRows de la clase Tab


Para migrar de OpenXava 4.6 a OpenXava 4.6.1

Mensajes en archivos i18n sin argumentos ahora son formateados de manera estándar

Esto es realmente el arreglo de un fallo, pero puede afectar tus mensajes i18n si estos contienen apóstrofes, por tanto has de cambiar:
mi_mensaje=T'ha dit que no
por
mi_mensaje=T''ha dit que no
Fíjate como hay que cambiar ' por ''.

Para migrar de OpenXava 4.5.1 a OpenXava 4.6

Sin consideraciones.

Para migrar de OpenXava 4.5 a OpenXava 4.5.1

Los editores personalizados han de especificar el atributo tabindex

Para estar en el orden correcto de tabulación los editores tienen que especificar tabindex="1" en su HTML, así:
<input id="<%=propertyKey%>"
    name="<%=propertyKey%>" class="<%=style.getEditor()%> <%=numericClass%>"
    type="<%=inputType%>"
    tabindex="1" <!-- Ahora hay que poner esto -->
    ...
/>

Para migrar de OpenXava 4.4.x a OpenXava 4.5

Select íntegro en baseCondition de @Tab ahora tiene que usar sintaxis JPQL y no SQL

A partir de v4.5 OpenXava usa JPA para obtener datos tabulares, antes usaba SQL. Esto significa que cuando uses baseCondition para escribir un select completo has de utilizar la sintaxis JPQL, SQL ya no se soporta.
Es decir, si tienes un select como este:
baseCondition =
    "select CODIGO, DESCRIPCION, FAMILIA.DESCRIPCION " +
    "from   XAVATEST.SUBFAMILIA, XAVATEST.FAMILIA " +
    "where  SUBFAMILIA.FAMILIA = FAMILIA.CODIGO"
Lo has de reescribir de esta forma:
baseCondition =
    "select e.codigo, e.descripcion, f.descripcion " +
    "from Subfamilia e, Familia f " +
    "where e.codigoFamilia = f.codigo"
La sintaxis de JPQL y SQL son muy parecidas, normalmente no es necesario hacer grandes cambios más allá de cambiar los nombres de tablas y columnas por nombres de propiedades y tablas. Has de usar e como alias para la entidad principal.

El atributo condition de @DescriptionsList ahora usa sintaxis JPQL y no SQL

A partir de v4.5 OpenXava usa JPA para obtener datos de los combos, por tanto has de usar sintaxis JPQL en condition. Si no usas condiciones demasiado complicadas y usas ${nombrePropiedad} en vez de nombre de columna, seguramente no tendrás que hacer ningún cambio. Sin embargo, puede ser que necesitas hacer algún cambio, especialmente si usas nombres de columna. Por ejemplo, el siguiente código ya no funciona:
@DescriptionsList(
    // No funciona porque IDCOSA es un nombre de columna, por eso JPA no lo reconoce
    condition="${cosa.codigo} = (SELECT IDCOSA FROM ${Cosa} WHERE nombre = 'COCHE')"
)
La solución es usar nombres de propiedades en vez de nombres de columnas, en este caso cambiando IDCOSA por codigo es suficiente para resolver el problema:
@DescriptionsList(
    // Funciona porque usamos el nombre de propiedad, codigo, en vez de IDCOSA
    condition="${cosa.codigo} = (SELECT codigo FROM ${Cosa} WHERE nombre = 'COCHE')"
)
Otra opción es escribir la sentencia completa en puro JPQL, dado que los ${} ya no son necesarios, como sigue:
@DescriptionsList(
    // Podemos usar JPQL puro sin ${nombrePropiedad}
    condition="e.cosa.codigo = (SELECT c.codigo FROM Cosa c WHERE c.nombre = 'COCHE')"
)
Si usas JPQL has de usar e como alias para la entidad principal.

@OnSelectElementAction no refresca por defecto su colección

Este nuevo comportamiento produce un rendimiento mucho mayor en la mayoría de los casos, especialmente cuando trabajas con una colección muy grande y seleccionas elementos que no cambian los datos de la colección. Sin embargo, si tienes un caso donde tu @OnSelectElementAction cambia el contenido de la colección has de refrescar las colecciones explicitamente, como sigue:
public class MiOnSelectElementAction extends OnSelectElementBaseAction {
 
    public void execute() throws Exception {
        hacerAlgoQueModificaLaColeccion();
        getView().refreshCollections(); // A partir de v4.5 has de añadir esta linea
    }
 
}

Para migrar de OpenXava 4.3.x a OpenXava 4.4

HtmlUnit actualizado de 2.5 a 2.9

HtmlUnit es la librería que se usa para simular un navegador desde las pruebas jUnit. Se ha actualizado a la versión 2.9. HtmlUnit ha renombrado y eliminado algunos métodos y clases, de hecho la gente de HtmlUnit está siempre refactorizando su librería (refactorizar es bueno para las aplicaciones pero no lo es tanto para una libreria). Lo más probable es que no tengas que cambiar nada en tus pruebas jUnit porque ModuleTestBase oculta HtmlUnit, sin embargo si usas la API de HtmlUnit directamente, usando getHtmlPage() de ModuleTestBase por ejemplo, quizás tengas que adaptar algunas llamadas a métodos.

Para migrar de OpenXava 4.2.x a OpenXava 4.3

Sin consideraciones.

Para migrar de OpenXava 4.1.x a OpenXava 4.2

Sin consideraciones.

Para migrar de OpenXava 4.0.1 a OpenXava 4.1

Nueva acción en lista y colecciones (para pruebas junit)

La lista y las colecciones tienen una nueva acción disponible (List.sumColumn), por lo tanto si compruebas todas las acciones presentes en tu prueba junit, tendrás que modificarlo para tener en cuenta la nueva acción "List.sumColumn":
private String [] accionesLista = {
  "Mode.detailAndFirst",
  "Mode.split",
  "List.filter",
  "List.customize",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
  "List.sumColumn" // AÑADE ESTA ENTRADA
};
assertActions(accionesLista);

Para migrar de OpenXava 4.0 a OpenXava 4.0.1

Ya no hay conversor por defecto para boolean

A partir de ahora no hay conversor por defecto denido en default-converters.xml para java.lang.Boolean y boolean. En realidad, esto no produce ningún problema de incompatibilidad en las aplicaciones JPA, ya que en estas aplicaciones el motor JPA hace la coversión el mismo. Sin embargo, si tienes una aplicación XML antigua, sólo has de regenerar el código y todo funcionará perfectamente, porque la mayoría de las bases de datos hace un buen trabajo al traducir de boolean a numérico automáticamente. De todas formas, puedes configurar tu aplicación para que funcione como antes, simplemente añade las siguiente líneas al archivo conversores.xml en la carpeta xava de tu aplicación:
<para-tipo tipo="boolean"
  clase-conversor="org.openxava.converters.Boolean01Converter"
  tipo-cmp="java.lang.Integer"/>
 
<para-tipo tipo="java.lang.Boolean"
  clase-conversor="org.openxava.converters.Boolean01Converter"
  tipo-cmp="java.lang.Integer"/>
Recuerda, añadir estás líneas no suele ser necesario, regenerar código sin más debería ser suficiente. Y si tu aplicación es JPA (el caso más normal) no necesitas hacer nada.

Para migrar de OpenXava 4m6 a OpenXava 4.0

Sin consideraciones.

Para migrar de OpenXava 4m5 a OpenXava 4m6

Hibernate actualizado a Hibernate 3.6

En OpenXava 4m6 Hibernate ha sido actualizado a Hibernate 3.6 para poder soportar JPA 2.0. La mayoría del código funciona sin hacer ninguna modificación. Sin embargo, hay algunos detalles que quizás tengas que modificar en tu código. Abajo encontrarás alguno de estos detalles.
Adicionalmente, es muy recomendable que repliegues (desinstales) tu vieja aplicación del servidor de aplicaciones, y la vuelvas a desplegar. Es decir, borra la vieja aplicación de la carpeta webapps del Tomcat, antes de desplegar una nueva versión de ésta basada en OX4m6, así nos aseguramos de que los viejos jars de JPA e Hibernate se han borrado. Borra también las carpetas .dist de tu workspace o workspace.dist.

Referencias @ManyToOne inexistentes usadas como @Id ya no están soportadas (Hibernate 3.6)

Hibernate 3.6 no soporta referencias @ManyToOne inexistentes usada como @Id. Es decir, si tienes una entidad con las siguientes claves:
public class Albaran {
 
  @Id @Column(length=5)
  private int numero;
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private TipoAlbaran tipo;  // El tipo ha de existir en la base de datos
  ...
}
En este caso el TipoAlbaran referenciado tiene que existir siempre en la base de datos.
Realmente, este es un caso muy raro que sólo te encontrarás cuando trabajes contra bases de datos legadas diseñadas por programadores la era pre-RDBMS (como los programadores RPG). Ellos a veces usan claves que incluyen referencias a otras tablas, y cuando esas referencias no existen ponen ceros en los campos. Si te encuentras con este caso puedes resolverlo de alguna de las siguientes maneras:
  • Crea una fila en la tabla referenciada con 0 como clave.
  • Usa una propiedad plana en vez de una referencia. En este caso puedes usar un editor especial para la propiedad.
  • Permite nulos para la columna usada como pseudo-clave-foranea y cambia todos los ceros por nulos en esa columna.

Para poder asignar una entidad ya existente ésta ha de ser 'manejada' (Hibernate 3.6)

Es decir, en las versiones previas de Hibernate podías escribir:
Albaran albaran = new Albaran();
TipoAlbaran tipoAlbaran = new TipoAlbaran(); // Creamos un nuevo TipoAlbaran
                                             // en lugar de buscarlo
tipoAlbaran.setNumero(66); // El TipoAlbaran 66 ya existe en la base de datos
albaran.setTipo(tipoAlbaran);
...
XPersistence.getManager().persist(albaran);
Pero, esto no funciona con Hibernate 3.6, en su lugar has de escribirlo lo siguiente:
Albaran albaran = new Albaran();
TipoAlbaran tipoAlbaran = XPersistence.getManager()
  .find(TipoAlbaran.class, 66); // Lo buscamos
albaran.setTipo(tipoAlbaran);
XPersistence.getManager().persist(albaran);

Entidad con solo una referencia @ManyToOne como clave (Hibernate 3.6)

Con versiones anteriores de Hibernate podías escribir el siguiente código en tu entidad:
@Entity
@IdClass(PersonaContactoClienteKey.class)
public class PersonaContactoCliente {
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private Cliente cliente;
 
  // No más campos @Id
 
  ...
 
}
Y la referencia de esta forma:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="CUSTOMERCONTACT") // Sin el atributo referencedColumnName
private PersonaContactoCliente personaContactoCliente;
Y esto funcionaba. Sin embargo, con Hibernate 3.6 esto no funciona. Afortunadamente, hay una forma de conseguir el mismo efecto. Escribe tu entidad de la siguiente forma:
@Entity // @IdClass ya no se usa
public class PersonaContactoCliente
  implements java.io.Serializable { // Tiene que implementar Serializable
 
  @Id @ManyToOne(fetch=FetchType.LAZY)
  private Cliente cliente;
 
  // No más campos @Id
 
  ...
 
}
Y la referencia de esta forma:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumns({
  @JoinColumn(name="CUSTOMERCONTACT",
    referencedColumnName="CUSTOMER_NUMBER") // referencedColumnName es obligatorio
})
private PersonaContactoCliente personaContactoCliente;

Type de Hibernate CharBooleanType no funciona (Hibernate 3.6)

CharBooleanType (y algunos otros types de Hibernate) ha sido marcado como obsoleto (deprecated), es más, no funcioa bien en Hibernate 3.6. Si tienes algún type que extienda de CharBooleanType, tienes que reescribirlo para extender de AbstractSingleColumnStandardBasicType. Mira SiNoType en el paquete org.openxava.types.

Entidades con @DiscriminatorColumn arroja errores (Hibernate 3.6)

Las entidades que contengan discriminador que sea parte de la clave, arrojarán error de campo duplicado. Suponga que tiene una entidad anotada de la siguiente manera:
@Entity
@Table(name = "`TABLAS`")
@DiscriminatorColumn(name="ID",
        discriminatorType=DiscriminatorType.STRING,
        length=20)
 
Hibernate 3.4 correrá sin problemas, pero la versión 3.6 (y me parece que la 3.5 también) les arrojará el error de campo duplicado. Para corregir esto debe utilizar una anotación dependiente de Hibernate @DiscriminatorOptions de la siguiente forma:
@Entity
@Table(name = "`TABLES`")
@DiscriminatorColumn(name="ID",
        discriminatorType=DiscriminatorType.STRING,
        length=20)
@DiscriminatorOptions(insert = false) // Anotacion dependiente de Hibernate
 
Y debe funcionar correctamente.

Método getProperty() renombrado en ModuleTestBase

El método getProperty() de ModuleTestBase ha sido renombrado como getXavaJUnitProperty(). Por tanto, si lo usas en tu prueba has de renombrar la llamada al método, como sigue:
String host = getProperty("host"); // Hasta v4m5
// Tiene que cambiarse por
String host = getXavaJUnitProperty("host"); // A partir de v4m6
Este cambio fue necesario para permitir usar Groovy al escribir pruebas JUnit.

Para migrar de OpenXava 4m4 a OpenXava 4m5

El controlador Navigation no se añade automáticamente

Hasta ahora el controlador Navigation (con las acciones anterior - inicio - siguiente en modo detalle) era añadido automáticamente a todos los módulos con detalle y lista. A partir de ahora, este controlador ya no se añadirá implícitamente. Esto no es un problema ya que Typical lo exteniende, pero si tienes un módulo con detalle - lista sin controlador Typical, en ese caso has de añadir Navigation explícitamente:
<modulo nombre="CambiarPrecioProducto">
  <modelo nombre="Producto"/>
  <controlador nombre="Navigation"/>  <!-- Has de añadir esto -->
  <controlador nombre="CambiarPrecioProducto"/>
</modulo>

Nuevo modo split (partido) - Cambios en jUnit

Además de detalle y lista, ahora tenemos un nuevo modo, split (partido), que permite mostrar la lista y el detalle al mismo tiempo. Esta funcionalidad no produce ninguna incompatibilidad a nivel de aplicación, pero si usas assertActions() en tus pruebas puede que tengas que añadir esta nueva acción:
String [] listActions = {
  "Print.generatePdf",
  "Print.generateExcel",
  "CRUD.new",
  "CRUD.deleteSelected",
  "Mode.detailAndFirst",
  "Mode.split", // HAS DE AÑADIR ESTO
  "List.filter",
  "List.customize",
  "List.orderBy",
  "List.viewDetail",
  "List.hideRows",
};
assertActions(listActions);
Si no te gusta este nuevo modo split, lo puedes quitar de tu applicación añadiendo la siguiente entrada en xava.properties:
defaultModeController=DetailList
En este caso el controlador de modo ya no es Mode sino DetailList, esto implica que has de cambiar tu pruebas junit:
// execute("Mode.list"); // NO si defaultModeController=DetailList en xava.properties
execute("DetailList.list"); // SÍ si defaultModeController=DetailList en xava.properties

Nueva acción CRUD.deleteRow - Cambios en jUnit

La acción CRUD.deleteSelected ha sido divida en CRUD.deleteSelected y CRUD.deleteRow. Si usas CRUD.deleteSelected con el argumento row, has de cambiarla por CRUD.deleteRow:
// execute("CRUD.deleteSelected", "row=2"); // NO, desde 4m5
execute("CRUD.deleteRow", "row=2"); // SI
Además, dado que CRUD.deleteRow está disponible por defecto en todos lo módulos, si usas assertActions() en tus pruebas puede que tengas que añadirla a la lista de acciones.

La vista (View) no es editable por defecto

A partir de ahora cuando se inicializa un módulo el objeto View no es editable. Esto no es un gran problema porque las acciones para nuevo y buscar establecen el estado correcto de editable en la vista. Pero si tienes una acción de nuevo o buscar personalizada puede que necesites modificarla para establecer el estado de editable explicitamente:
public class MiAccionBuscar extends ViewBaseAction {
 
  public void execute() throws Exception {
    ...
    getView().setKeyEditable(false);  // Has de llamar a setKeyEditable()
    getView().setEditable(true);      // y setEditalbe() explicitamente
    ...
  }
 
}

Para migrar de OpenXava 4m3 a OpenXava 4m4

CRUD.search ahora usa un diálogo - Cambios en jUnit

La acción CRUD.search ahora usa un diálogo para introducir los datos de búsqueda. Esto implica que todas tus pruebas junit que usen CRUD.search fallarán. Es decir, si tienes una prueba como la siguiente:
setValue("codigo", "1");
execute("CRUD.search");
assertValue("descripcion", "Número uno");
No funcionará. Has de reescribirla. Para hacerlo, tienes 2 opciones. La primera es adaptar tu prueba al nuevo comportamiento de la acción CRUD.search:
execute("CRUD.search"); // Muestra un diálogo
setValue("codigo", "1");
execute("Search.search"); // Hace la búsqueda y cierra el diálogo
assertValue("descripcion", "Número uno");
La segunda es cambiar "CRUD.search" por "CRUD.refresh", ya que la vieja CRUD.search ha sido renombrada como CRUD.refresh:
setValue("numero", "1");
execute("CRUD.refresh"); // En lugar de CRUD.search
assertValue("descripcion", "Número uno");
Además, dado que CRUD.refresh está disponible por defecto en todos lo módulos, si usas assertActions() en tus pruebas puede que tengas que añadirla a la lista de acciones.

Para migrar de OpenXava 4m2 a OpenXava 4m3

MapFacade.getValues() incluye el nombre del modelo en el resultado

MapFacade.getValues() ahora incluye el nombre del modelo en el resultado, con una entrada con la clave MapFacade.MODEL_NAME. Si usas la clases estándar de OpenXava (como View o PropertiesManager) todo funcionará bien, pero si tienes código personalizado puede ser que falle por culpa de esta nueva entrada inexeperada. En este caso quita la entrada de los valores, de esta forma:
Map valores = MapFacace.getValues("Persona", clave, miembros);
valores.remove(MapFacade.MODEL_NAME); // Puede que necesites esta línea

Método Classes.getSimpleName() eliminado

El método getSimpleName() de Classes ha sido eliminado. Usa getSimpleName() de Class available de Java 5 en su lugar.
Cambia esto:
Classes.getSimpleName(laClase);
por esto otro:
laClase.getSimpleName();

Para migrar de OpenXava 4m1 a OpenXava 4m2

Atributos mostrar-dialogo y ocultar-dialogo quitados de <accion/>

La forma declarativa de mostrar un diálogo ha sido sustituida por una programática en v4m2. La nueva forma es más flexible y requiere menos código, aunque la razón real para hacer este cambio es que la forma declarativa obliga al desarrollador a tocar controladores.xml cada vez que se hace una mejora en las acciones estándar con los diálogos. Es decir, con la forma declarativa muchas mejoras en OX requerirían muchas instrucciones de migración para que el desarrollador pueda actualizar su aplicación. Con el nuevo enfoque programático, el desarrollador puede actualizarse su versión de OX y disfrutar, sin tener que tocar su aplicación.
La mala noticia es que has de reescribir tu código con diálogos, ahora en vez de marcar tu acción con mostrar-dialogo y ocultar-dialogo, tienes que usar los métodos showDialog() y closeDialog(). Compara la nueva forma con la vieja para más detalles.

Las colecciones usan diálogos para editar, ver y añadir detalles - Cambios en acciones

Todas las acciones que extienden de CollectionBaseAction o CollectionElementViewBaseAction mantienen su comportamiento original, por tanto no necesitas hacer ningún cambio en la mayoría de tus acciones de colección. Pero, si tienes alguna acción de detalle que extienda directamente de ViewBaseAction quizás tengas que cambiar la forma de acceder a la vista padre. Recuerda que ahora estás dentro de un diálogo:
public class MiAccionDetalleParaColeccion extends ViewBaseAction  {
 
    public void execute() throws Exception {
        ...
        getView().setValue("nombre", "Pepe"); // Ahora getView() es la vista del diálogo
        getPreviousView().setValue("nombre", "Pepe"); // getPreviousView() es la vista
                                                      // que ha abierto el diálogo
        closeDialog();
    }
}
 
Es decir, quizás tengas que cambiar getView() por getPreviousView() en alguna de tus acciones.

Las colecciones usan diálogos para editar, ver y añadir detalles - Cambios en jUnit

Esto no afecta al código de tu aplicación, pero dado que el comportamiento de las colecciones ha cambiado, has de adaptar tu pruebas junit. La principal diferencia es que el usuario ahora usa un diálogo para editar la línea de detalle de la colección, por tanto el resto de las acciones y valores de la interfaz de usuario principal no están disponibles, ya que se usa un diálogo modal.
Ahora los miembros de la vista de detalle están en la vista raíz, por tanto tienes que quitar el prefijo de colección cuando referencias miembro del elemento de la colección:
// lineas es el nombre de la colección
setValue("lineas.cantidad", "6");  // Ahora ¡INCORRECTO! Has de quitar 'lineas'
setValue("cantidad", "6"); // ¡CORRECTO! Sin nombre de colección
También las acciones disponible al editar el elemento de una colección (por ende dentro de un diálogo) no usan ningún argumento:
execute("Collection.save", "viewObject=xava_view_section1_lineas"); // ¡INCORRECTO!
execute("Collection.save"); // ¡CORRECTO!
Si quieres acceder a las acciones o miembro de la vista principal, has de cerras el diálogo primero:
execute("Factura.editarLinea", "row=1,viewObject=xava_view_section1_details");
assertValue("cantidad", "234");
closeDialog(); // Necesario antes de ejecutar CRUD.save
execute("CRUD.save");
Al grabar el elemento de una colección el diálogo se cierra, por eso si quieres añadir otro detalle has de abrir otra vez el diálogo:
execute("Collection.save"); // Esto cierra el diálogo
execute("Collection.new", // Es necesario llamar a 'new' de nuevo, para abrir el diálogo
  "viewObject=xava_view_section1_lineas");
En las colecciones anidadas has de cambiar el valor del argumento viewObject de las acciones de fila, otra vez por causa de que está dentro de un diálogo que es la vista raíz:
execute("Collection.new",
  "viewObject=xava_view_lugaresEntrega_recepcionistas"); // ¡INCORRECTO!
execute("Collection.new",
  "viewObject=xava_view_recepcionistas"); // ¡CORRECTO! Solo el nombre de la
                                          // última colección anidada
Esto no solo aplica a viewObject sino también a otras referencias a la colección anida en el argumento de la acción. Fíjate en el siguiente ejemplo:
// ¡INCORRECTO!: Usando "lugaresEntrega.recepcionistas", el nombre calificado
setConditionValues("lugaresEntrega.recepcionistas", new String[] { "J" } );
execute("List.filter", "collection=lugaresEntrega.recepcionistas");
assertCollectionRowCount("lugaresEntrega.recepcionistas", 1);
assertValueInCollection("lugaresEntrega.recepcionistas", 0, 0, "JUAN");
 
// ¡CORRECTO!: Usando "recepcionistas", el nombre simple
setConditionValues("recepcionistas", new String[] { "J"} );
execute("List.filter", "collection=recepcionistas");
assertCollectionRowCount("recepcionistas", 1);
assertValueInCollection("recepcionistas", 0, 0, "JUAN");
En general, si tu prueba falla trata de quitar el nombre de colección como prefijo del nombre de miembro, argumento de acción, etc.

Acción de fila para las colecciones de entidades es por defecto view y no edit

No has de cambiar el código de la aplicación, solo el código de pruebas:
// Solo para colecciones de entidades sin @AsEmbedded
execute("Collection.edit",
  "row=0,viewObject=xava_view_clientes"); // ¡INCORRECTO! 'edit' ya no se usa
execute("Collection.view",
  "row=0,viewObject=xava_view_clientes"); // ¡CORRECTO! Ahora es la acción
                                          // 'view' la que se usa
Esto también implica que los elementos de la vista no tienen editable las propiedades clave y no tienen acción para borrar. Puede ser que tengas que adaptar tu prueba:
// Dentro de un diálogo que visualiza el elemento de colección
assertEditable("numero"); // ¡INCORRECTO! Los campos clave no son editable
execute("Collection.remove"); // ¡INCORRECTO! 'remove' no está disponible
Este cambio no aplica a colecciones con @AsEmbeddable, CascadeType.REMOVE o CascadeType.ALL.

Para migrar de OpenXava 3.1.4 a OpenXava 4m1

BaseAction implementa IModuleContextAction

BaseAction ahora implementa IModuleContextAction, por tanto si alguna de tus acciones lo implementa has de reescribir el método setContext() llamando a super.setContext(). De esta manera:
public class MiAccion extends BaseAction implements IModuleContextAction {
    public void setContext(ModuleContext context) {
        super.setContext(context);  // Tienes que añadir esta línea
        this.context = context;
    }
}
Otra opción es quitar el implements IModuleContextAction y el método setContext(), y usar el método protegido getContext() de BaseAction, para acceder al contexto.

Objeto de sesión xava_currentReferenceLabel eliminado

Nota: Este cambio no es necesario si actualizas directamente a 4m2 o superior, porque desde 4m2 inyectar usando <usa-objeto /> en una propiedad inexistente no falla, sino que produce un simple mensaje de advertencia.
El objeto de sesión xava_currentReferenceLabel ya no se usa; por tanto ha sido eliminado de default-controllers.xml. Esta objeto se usaba por las acciones de búsqueda de las referencias, por tanto si tienes una acción para buscar referencias propia has de quitar la referencia a xava_currentReferenceLabel en tu controladores.xml, tal como muestra el siguiente código:
<controlador nombre="MiReferencia">
    <accion nombre="buscar" oculta="true"
        mostrar-dialogo="true"
        clase="org.openxava.test.acciones.BuscarMiReferencia"
        imagen="images/search.gif">
        <usa-objeto nombre="xava_view"/>
        <usa-objeto nombre="xava_referenceSubview"/>
        <!-- Esta línea se tiene que quitar
        <usa-objeto nombre="xava_currentReferenceLabel"/>
        -->
        <usa-objeto nombre="xava_tab"/>
    </accion>
</controlador>
También es conveniente para las acciones de búsqueda y otras acciones de referencias usar mostrar-dialogo="true" (mostrar-dialogo ha sido quitado en v4m2) para mostrar la búsqueda en un diálogo, tal como hacen las acciones de búsqueda estándar de OX.

Para migrar de OpenXava 3.1.3 a OpenXava 3.1.4

Esquema de tabla de AccessTracking cambiado

En el proyecto AccessTracking el esquema de la tabla para registrar los accesos ha cambiado:
  • USER ahora es USER_NAME
Es necesario cambiar nuestras tabla actual si queremos actualizar a AccessTracking 3.1.4
Este cambio se ha hecho para que AccessTracking pueda funcionar en bases de datos que no soporten USER como nombre de columna.

Para migrar de OpenXava 3.1.1 a OpenXava 3.1.2/3.1.3

Sin consideraciones.

Para migrar de OpenXava 3.1 a OpenXava 3.1.1

La generación de ids para elementos HTML ha cambiado para soportar multimódulo por página

Para poder soportar varios módulos en la misma página de un portal; OX, desde v3.1.1, cambia la forma en que los ids de los elementos HTML son generados. Esto no tiene efecto en el código de nuestra aplicación ya que la manipulación directa de elementos HTML es algo raro en una aplicación OpenXava típica. Sin embargo, necesitaremos hacer algunos cambios leves en nuestras pruebas junit.
Cuando usemos xava.keyProperty como argumento en una acción dentro de la prueba junit, ya no usaremos xava.ModelName como prefijo nunca más. Es decir, hemos de cambiar:
execute("Albaran.generarNumero", "xava.keyProperty=xava.Albaran.numero");
por
execute("Albaran.generarNumero", "xava.keyProperty=numero");
Tan solo eliminamos xava.Albaran en este caso.
Para evitar una migración demasiado laboriosa OpenXava todavía soporta el viejo estilo para todas las acciones del controlador Reference.
Además, si inspeccionamos directamente el documento HTML usando los ids, hemos de decorarlos con el método decorateId(). Es decir, si tenemos algo como esto:
HtmlImage imagen = (HtmlImage)
  page.getHtmlElementsByName("xava.Formula.ingredientes.imagen").get(0);
Necesitamos cambiarlo por el siguiente código:
HtmlImage imagen = (HtmlImage)
  page.getHtmlElementsByName(decorateId("ingredientes.imagen")).get(0);
Aquí usamos decorateId(). Fijémonos también en que hemos quitado el prefijo xava.Formula.

Para migrar de OpenXava 3.0.3 a OpenXava 3.1

El código JavaScript de los editores tiene que moverse desde los JSPs a custom-editors.js

Si alguno de nuestros editores personalizados define funciones JavaScript dentro del JSP, hemos de moverlos a un archivo con el nombre custom-editors.js (puede que necesitemos crearlo) en la carpeta web/xava/js de nuestro proyecto. Nota: A partir de v4m3 se pude poner el código JavaScript para los editore en cualquier archivo, no importa el nombre, en la carpeta web/xava/editors/js. De esta forma puedes tener uno o más archivos por cada editor, y es puedes incluir librerías de tercero fácilmente.
Es decir, si tenemos un editor llamado mapaGoogleEditor.jsp con una función JavaScript llamada muestraMap(), justo de esta forma:
<script>
function muestraMapa(v) {
  ...
}
</script>
 
<!-- Aquí código JSP -->
Hemos de moverla a custom-editors.js, de esta forma:
if (openxava == null) var openxava = {};
if (openxava.editors == null) openxava.editors = {};
 
// mapaGoogleEditor
if (openxava.editors.mapaGoogle== null) openxava.editors.mapaGoogle= {};
openxava.editors.mapaGoogle.muestraMapa = function(v){
  ...
}
 
Ahora dentro de nuestro editor en vez de llamar a la función de esta forma:
<input ... onclick="muestraMapa(valor)"/>
hemos de hacerlo calificando la función:
<input ... onclick="openxava.editors.mapaGoogle.muestraMapa(valor)"/>

Llamar al método View.refreshCollections() cuando se modifiquen los datos de una colección

Desde OpenXava 3.1 solo los datos modificados se refrescan en la vista. Cuando el usuario pulsa en una acción de una colección la colección se refresca automáticamente, pero si nuestra acción está fuera de la colección entonces no hay manera de saber si los datos de la colección se han modificado. En este caso necesitamos llamar explícitamente a View.refreshCollections(). Por ejemplo:
// No es una acción de una colección
public class TraducirTodosNombresTransportistas extends ViewBaseAction {
 
    public void execute() throws Exception {
        for (Iterator it=Transportista.findAll().iterator(); it.hasNext(); ) {
            Transportista t = (Transportista) it.next();
            t.traducir(); // El transportista se modifica,
                // estos datos se muestran en una colección de la vista
        }
        getView().refreshCollections(); // Para refrescar los datos de
            // las colecciones visualizadas
    }
 
}
Es decir, quizás necesitemos añadir getView().refreshCollections() si los datos de la colección no se refrescan después de ejecutar nuestra acción.

Más librerías necesarias en MANIFEST.MF (solo para EJB2)

Hemos de editar el archivo build/ejb/META-INF/MANIFEST.MF, y añadir los siguientes archivos ./lib/slf4j-api.jar ./lib/slf4j-jdk14.jar ./lib/javassist.jar a la lista de jars.
Esto solo aplica si estamos usando EJB (generando un EAR). Mirar OpenXavaTest/build/ejb/META-INF/MANIFEST.MF para una lista de jars completa y actualizada.

Para migrar de OpenXava 3.0.2 a OpenXava 3.0.3

HttpUnit reemplazado por HtmlUnit para las pruebas junit usando ModuleTestBase

HttpUnit ha sido reemplazado por HtmlUnit para las pruebas junit basadas en ModuleTestBase. La razón principal es el precario soporte de AJAX que ofrece HttpUnit.
La mayoría de nuestras pruebas junit basadas en ModuleTestBase seguirán funcionando sin tocarlas. HtmlUnit funciona como un navegador de verdad, permitiendo probar mejor nuestras aplicaciones, pero hay algunos pequeños cambios que puede que necesitemos hacer en algunas de nuestras pruebas junit con algún caso especial.
Estos son algunos de los cambios en ModuleTestBase:

Es obligado usar argumentos exactos para execute()

Es decir, si escribimos en nuestra prueba:
execute("Reference.search", "keyProperty=xava.Transportista.almacen.codigoZona");
y el vínculo en la pagína tiene keyProperty=xava.Transportista.almacen.codigo, es decir, no es exactamente igual; en el caso de HttpUnit funciona, pero en el caso de HtmlUnit no. No podemos ejecutar acciones que no estén disponible al usuario mediante botones o vínculos, además nuestra prueba tiene que ejecutar la acción exactamente de la misma forma que lo hace el usuario.

Los métodos allowDuplicateSubmit() y click() han sido eliminados

Hasta ahora, cuando queríamos simular un click del usuario necesitábamos un código como este:
allowDuplicateSubmit();
click("MiControlador.miAccion");
Llamar a allowDuplicateSubmit() es obligado antes de usar click(). El método click() lanza los eventos asociados al botón o vínculo pero no funciona bien en muchos casos. Desde ahora, usando HtmlUnit, el execute() simula a click(), y lo hace bien, por tanto click() y allowDuplicateSubmit() ya no son necesarios. Si tenemos un código como el de arriba podemos sustituirlo por algo así:
execute("MiControlador.miAccion");

El método getForm() devuelve un HtmlForm

El método protegido getForm() de ModuleTestBase que antes devolvía un WebForm de HttpUnit ahora devuelve un HtmlForm de HtmlUnit. Si lo estamos usando en alguna prueba hemos de reescribirla. Afortunadamente este método es usado ráramente.

El método getConversation() reemplazado por getWebClient()

El método protegido getConversation() de ModuleTestBase que antes devolvía WebConversation() de HttpUnit ha sido reemplazado por el método getWebClient() de HtmlUnit que devuelve un WebClient. Si lo estamos usando en alguna prueba hemos de reescribirla. Afortunadamente este método es usado ráramente.

Uso más fácil de setConditionValue

Antes teníamos que escribir:
String [] condicion= { " ", "", "", "V" };
setConditionValues(condicion);
Cuando queríamos rellenar el cuarto elemento y el segundo era un combo (un enum o boolean). Notemos que necesitabamos poner un espacio en blanco como primer elemento, realmente en todos los que había antes del combo. Este truco, necesario por culpa de HttpUnit, ya no hace falta más. Ahora podemos escribir:
String [] totalCondition = { "", "", "", "V" };
setConditionValues(totalCondition);
Sin preocuparnos por poner espacios en blanco, aunque si los ponemos también funciona.

Para migrar de OpenXava 3.0.1 a OpenXava 3.0.2

Mensaje de objeto no encontrado incluye valores de la clave de búsqueda (para pruebas junit)

Esto puede requerir algún ligero cambio en nuestras pruebas junit. Tenemos que cambiar un código como este en nuestra prueba:
assertError("No encontrado el objeto de tipo Factura con es clave");
por
assertError("No encontrado el objeto de tipo Factura con clave Año:2008, Número:1");

Ya no se usa Hibernate para las preferencias de usuario

Ahora se usa Java Preferences para almacenar las preferencias de usuario. OpenXavaDS y openxava-db ya no son necesarios.
Por tanto, hemos de borrar TabUserPreferences.hbm.xml y openxava-hibernate.cfg.xml de la carpeta persistence de nuestro proyecto.

Para migrar de OpenXava 3.0 a OpenXava 3.0.1

Las anotaciones de validación ahora son restricciones de Hibernate Validator

@Required, @PropertyValidator y @EntityValidator están definidas desde 3.0.1 como restricciones Hibernate Validator. Esto quiere decir que cuando grabamos usando directamente la api de JPA, estas validaciones se aplicarán.
Es decir, si tenemos una entidad como esta:
@Entity
public class Cliente {
 
    @Required
    private int codigo;
 
    @Required
    private String nombre;
 
    @Required
    private String observaciones;
 
    ...
 }
Y ejecutamos el siguiente código:
Cliente c = new Cliente();
c.setCodigo(1);
c.setNombre("JUANITO");
// Dejamos la propiedad observaciones vacía
XPersistence.getManager().save(c);
XPersistence.commit();
El código funciona con OX3.0, pero falla con OX3.0.1, porque en OX3.0.1 la restricción @Required se aplica cuando grabamos usando JPA. En OX3.0, y anteriores, la validación se aplicaba solo cuando usábamos OpenXava (con MapFacade, o las acciones estándar de OX).
Para arreglar este caso, por ejemplo, solo necesitamos llenar la propiedad observaciones antes de grabar.

Ligera mejora en la acción 'new' de CRUD

Ahora la acción new activa automáticamente la sección inicial. Esto puede romper algunas pruebas junit. Por ejemplo, si tenemos este código:
execute("Sections.change", "activeSection=2");
...
execute("CRUD.new");
setValue("propiedadEnSeccion2", "el valor"); // Esta propiedad está en la sección 2
En este caso tenemos que volver a la sección 2 explicitamente:
execute("Sections.change", "activeSection=2");
...
execute("CRUD.new");
// Tenemos que añadir la siguiente línea, porque después de 'new' estamos en la sección 0
execute("Sections.change", "activeSection=2");
setValue("propiedadEnSeccion2", "el valor"); // Esta propiedad está en la sección 2
 

Para migrar de OpenXava 2.2.5 a OpenXava 3.0

El proveedor de persistencia por defecto es JPA

Desde la v3.0 OpenXava usa JPA por defecto para la persistencia. Si quieres seguir usando Hibernate como proveedor de persistencia en tu aplicación pon la siguiente línea en el archivo xava.properties de tu proyecto:
persistenceProviderClass=org.openxava.model.impl.HibernatePersistenceProvider

MapFacade ya no lanza RemoteException

Ahora los método de MapFacade no lanzan RemoteException sino SystemException, que es una excepción runtime.
Esto tiene poca repercusión en tu código, pero si tienes algo así:
try {
    MapFacade.validate("Factura", valores);
}
catch (RemoteException ex) {
    ...
}
Entonces tendrás que cambiar la RemoteException por una SystemException:
try {
    MapFacade.validate("Factura", valores);
}
catch (SystemException ex) {
    ...
}
Además, XavaException ahora es una excepción runtime. Pero esto no implica ningún cambio en tu código.

Para migrar de OpenXava 2.2.4 a OpenXava 2.2.5

MapFacade no es autocommit a partir de ahora

Hasta ahora, cuando escribiamos:
MapFacade.create("Cliente", valoresCliente);
MapFacade.create("Factura", valoresFactura);
Estas dos líneas eran dos transacciones. Si la creación de la factura fallaba el cliente se grababa. Es decir, MapFacade tenía una política de autocommit.
Desde ahora MapFacade no es autocommit por defecto, es decir, el caso de arriba tendrá solo una transacción, confirmada por OX al final de la acción o el test. Ahora, si la creación de la factura falla la creación del cliente no se producirá.
Esto puede alterar ligeramente el comportamiento de nuestras acciones en caso de fallo, pero solo si nuestras ascciones hacen varias llamadas a MapFacade. Si queremos preservar el comportamiento anterior tenemos dos opciones.
Primera opción: añadir la siguiente línea a nuestro archivo properties/xava.properties:
mapFacadeAutoCommit=true
Segunda opción: confirmar la acción manualmente. Por ejemplo, el código de arriba se puede escribir de esta forma:
MapFacade.create("Cliente", valoresCliente);
MapFacade.commit();
MapFacade.create("Factura", valoresFactura);
MapFacade.commit();

Para migrar de OpenXava 2.2.3 a OpenXava 2.2.4

El esquema para table de imagenes del estereotipo GALERIA_IMAGENES

Ahora el esquema para la table de imagenes se especifica separadamente, es decir,
Now the schema for image table is specified specified separately, that is, ante escribiamos esto en nuestro archivo de propiedades de configuración:
images.table=XAVATEST.IMAGES
Ahora hemos de escribir:
images.schema=XAVATEST
images.table=IMAGES

Para migrar de OpenXava 2.2.2 a OpenXava 2.2.3

Las etiquetas del modo lista y colecciones son calificadas (para las pruebas junit)

Las etiquetas pare el modo lista y las colecciones ahora son calificadas, es decir si tenemos una propiedad cliente.nombre, antes la etiqueta era Nombre, y ahora es Nombre de Cliente. Esto puede afectar nuestras pruebas junit, es decir, si tenemos:
assertLabelInList(2, "Nombre"); // de cliente.nombre
ahora tenemos que escribir:
assertLabelInList(2, "Nombre de Cliente"); de cliente.nombre

Esquema de tabla de AccessTracking cambiado

En el proyecto AccessTracking el esquema de la tabla para registrar los accesos ha cambiado:
  • TABLE ahora es TABLE_NAME
  • DATE ahora es ACCESS_DATE
  • TIME ahora es ACCESS_TIME
Es necesario cambiar nuestras tabla actual si queremos actualizar a AccessTracking 2.2.3
Este cambio se ha hecho para que AccessTracking pueda funcionar en bases de datos que no soporten TABLE, DATE y TIME como nombre de columna.

Para migrar de OpenXava 2.2.1 a OpenXava 2.2.2

Sin consideraciones.

Para migrar de OpenXava 2.2 a OpenXava 2.2.1

MoneyFormatter (para pruebas junit)

Un formateador de dinero es aplicado por defecto para formatear o analizar todos los valores con el estereotipo DINERO, ahora toda la información de tipo dinero es siempre visualizada usando dos cifras decimales. Por tanto, hemos de adaptar nuestras pruebas junit, cambiando líneas como esta:
assertValue("importe", "20");
por algo así:
assertValue("importe", "20.00");
O, si así lo preferimos podemos usar la vieja forma de formatear, solo hemos de desactivar el formateador o definir el nuestro propio editando nuestro archivo editores.xml.

Acción 'Mode.list" no está disponible cuando el usuario navega a otra vista (para pruebas junit)

Cuando el usuario navega a otra vista (por ejemplo para crear o modificar una referencia) el vínculo para ir al modo lista ahora no está presente. Quizás necesites cambiar tu prueba junit:
Por ejempo, en este código junit:
execute("Reference.createNew", "model=Family2,keyProperty=xava.Product2.family.number");
assertAction("Mode.list"); // Desde 2.2.1 falla
El assertAction("Mode.list") se tiene que quitar

Para migrar de OpenXava 2.1.5 a OpenXava 2.2

El comportamiento por defecto para las colecciones de entidades cambia

Ahora, cuando el usuario pulsa en 'Añadir' en una colección de entidades, va a una lista donde puede escoger varias entidades para añadir. Esto puede causar que nuestro actual código JUnit falle. Necesitamos hacer unas simples modificaciones; sencillamente cambiar código como este en nuestras pruebas JUnit:
execute("Collection.new", "viewObject=xava_view_customers");
setValue("customers.number", getCustomerNumber2());
assertValueIgnoringCase("customers.name", getCustomer2().getName());
assertCollectionRowCount("customers",0);
execute("Collection.save", "viewObject=xava_view_customers");
assertCollectionRowCount("customers",1);
por este otro:
assertCollectionRowCount("customers",0);
execute("Collection.add", "viewObject=xava_view_customers");
assertValueInList(5, 0, getCustomer2().getName());
execute("AddToCollection.add", "row=5");
assertMessage("1 element(s) added to Customers of Seller");
assertCollectionRowCount("customers",1);
Además, el usuario ahora puede añadir varias entidades a la vez, esto es, un código como este:
execute("Collection.new", "viewObject=xava_view_customers");
setValue("customers.number", getCustomerNumber1());
assertValueIgnoringCase("customers.name", getCustomer1().getName());
assertCollectionRowCount("customers", 0);
execute("Collection.save", "viewObject=xava_view_customers");
assertMessage("Customer associated to Seller");
 
assertCollectionRowCount("customers", 1);
setValue("customers.number", getCustomerNumber2());
assertValueIgnoringCase("customers.name", getCustomer2().getName());
execute("Collection.save", "viewObject=xava_view_customers");
assertCollectionRowCount("customers",2);
se puede escribir así:
execute("Collection.add", "viewObject=xava_view_customers");
assertValueInList(4, 0, getCustomer1().getName());
assertValueInList(5, 0, getCustomer2().getName());
checkRow(4);
checkRow(5);
execute("AddToCollection.add");
assertMessage("2 element(s) added to Customers of Seller");
assertCollectionRowCount("customers",2);

El comportamiento por defecto para las colecciones de agregados cambia

Ahora, cuando un detalle de una collección se graba, la vista del detalle no se oculta, esto puede causar que nuestro actual código JUnit falle. Necesitamos hacer unas simples modificaciones; sencillamente cambiar código como este en nuestras pruebas JUnit:
execute("Collection.save", "viewObject=xava_view_section1_details");
execute("Collection.new", "viewObject=xava_view_section1_details"); // A borrar
por este otro:
execute("Collection.save", "viewObject=xava_view_section1_details");
Es decir, borrar la llamada a "Collection.new", porque despues de grabar el detalle, la acción "new" se ejecuta automáticamente, así la interfaz de usuario está lista para introducir un nuevo detalle.

Para migrar de OpenXava 2.1.4 a OpenXava 2.1.5

No hay consideraciones.

Para migrar de OpenXava 2.1.3 a OpenXava 2.1.4

Nuevas acciones en colecciones (para pruebas junit)

Las collecciones tienen nuevas acciones disponibles para los usuarios, por tanto si comprobamos todas las acciones presentes en nuestras pruebas junit hemos de modificar nuestras pruebas para que tengas en cuenta las nuevas acciones.
Es decir, si tenemos algo como esto en nuestro código de prueba junit:
        String [] acciones = {
            "Navigation.previous",
            "Navigation.first",
            "Navigation.next",
            "CRUD.new",
            "CRUD.save",
            "CRUD.delete",
            "CRUD.search",
            "Collection.new",
            "Collection.removeSelected"
        };
        assertActions(acciones);
hemos de cambiarlo por:
    String [] acciones = {
            "Navigation.previous",
            "Navigation.first",
            "Navigation.next",
            "CRUD.new",
            "CRUD.save",
            "CRUD.delete",
            "CRUD.search",
            "Collection.new",
            "Collection.removeSelected",
            "List.filter",        // Nuevo
            "List.orderBy",       // Nuevo
            "List.customize",     // Nuevo
            "List.hideRows",      // Nuevo
            "Print.generatePdf",  // Nuevo
            "Print.generateExcel" // Nuevo
        };
        assertActions(acciones);

Tarea Ant generarPortlets eliminada

La tarea ant generarPorltets ha sido quitada de OpenXava/build.xml porque ahora es exactamente igual que generatePortlets. Por lo tanto, si en tu build.xml tienes algo como esto:
<target name="generarPortlets">
    <ant antfile="../OpenXava/build.xml" target="generarPortlets"/>
</target>
Tienes que cambiarlo por:
<target name="generarPortlets">
    <ant antfile="../OpenXava/build.xml" target="generatePortlets"/>
</target>

Para migrar de OpenXava 2.1 a OpenXava 2.1.3

Pruebas JUnit y claves sin valor interpretadas como cero

Desde 2.13 si una propieda clave de tipo int, long o short no tiene valor en la vista cuando es interpretada, es interpretada como nulo (sin valor), y no como cero. Esto no tiene efecto en el usuario final, pero posiblemente necesitemos cambiar algunas pruebas JUnit, por ejemplo
Since 2.1.3 if a property key of type int, long or short has no value in view when it is parsed is parsed with null (without value), and not as zero. This has no effect in final user, but possibly you need to modify some junit test. Por ejemplo si tenemos una prueba así:
public void testAlgo() throws Exception {
  assertValue("codigo", "");
  execute("MiControlador.miAccion"); // Esto no cambia el valor de 'codigo'
  assertValue("codigo", "0"); // porque OX interpreta una cadena vacía como un 0 (hasta 2.1.2)
  ...
}
Ahora hemos de escribirlo así:
public void testAlgo() throws Exception {
  assertValue("codigo", "");
  execute("MiControlador.miAccion"); // Esto no cambia el valor de 'codigo'
  assertValue("codigo", ""); // porque ahora (desde 2.1.3) OX interpreta cadena vacía como nulo
  ...
}

Para migrar de OpenXava 2.0.4 a OpenXava 2.1

Proyectos WebSphere

Si despliegas tus proyectos en WebSphere necesitas hacer algunos pequeños ajustes:
Primero, en el archivo hibernate/hibernate.cfg.xml de tu proyecto añade el siguiente código marcado en azul:
<session-factory>
  <property
    name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property>
  <property name="hibernate.dialect">@hibernate.dialect@</property>
  <property name="hibernate.jdbc.use_get_generated_keys">false</property>
  <property name="hibernate.show_sql">false</property>
  @hibernate.properties@
  ...
</session-factory>
Segundo, en tu archivo de configuración para websphere (por ejemplo websphere-as400.properties) has de añadir:
hibernate.properties=<property name="hibernate.transaction.manager_lookup_class">\n\
\t\t\torg.hibernate.transaction.WebSphereTransactionManagerLookup\n\
\t\t</property>\n\
\t\t<property name="transaction.factory_class">\n\
\t\t\torg.hibernate.transaction.JTATransactionFactory\n\
\t\t</property>

Otros cambios que requieren migración

  • La tarea ant wtpBuild ha sido quitada de OX; podemos usar la tarea 'reconstuir' en su lugar. Llamar automáticamente a una tarea ant desde el Builder de Eclipse es lento, por tanto puede ser preferible llamar manualmente a la tarea ant 'reconstruir' bajo demanda (cuando el código XML de nuestra aplicación cambie).

Para migrar de OpenXava 2.0.3 a OpenXava 2.0.4

Parse de valores numéricos

Ahora los datos de tipo Number (Integer, BigDecimal, Short, etc) y Boolean (no boolean) son interpretados como nulo si en la interfaz de usuario están en blanco. Antes los campos numérico en blanco se interpretaban como 0. Este cambio no produce grandes incompatibilidades porque default-converters This change does not produce big incompatibility problems because default-converters.xml define las conversiones reales antes de grabar en la base de datos (que es lo que de verdad importa). Es decir, este cambio afecta solo a la visualización. Tus asuntos de incompatibilidad pueden ser:
  • La interfaz gráfica de la aplicación visualizar campos vacíos en vez de 0, cuando el formulario se reinicie.
  • En el test junit puede ser que recibas un blanco donde antes recibías un 0
  • Si usas View.getValue() para un Number puede valer null

Cambios en las API

  • Dates.clonWithoutTime() se ha renombrado a Dates.cloneWithoutTime()

Para migrar de OpenXava 2.0.2 a OpenXava 2.0.3

No se lanzan eventos al-cambiar cuando se busca

La guía de referencía (en la sección 7.5) dice que CRUD.searchByViewKey no lanza ningún evento al-cambiar, y CRUD.searchExecutingOnChange lanza todos los eventos al-cambiar. Pero por causa de un bug en ox2.0.2 (y anteriores) CRUD.searchByViewKey lanzaba al-cambiar de las claves en las referencias, y CRUD.searchExecutingOnChange no lanzaba al-cambiar de las claves en las referencias. Este problema ha sido resuelto, por la tanto si tienes código que confía en este comportamiento erroneo deberás adaptarlo.

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit tiene que hacerse usando POJOs, el uso de claves primarias EJB2 no está soportado.
Ver documentación en Para migrar de OpenXava 1.2.1 a OpenXava 2.0 below.

Para migrar de OpenXava 2.0.1 a OpenXava 2.0.2

La acción Collection.hiddenDetail ha sido renombrada a Collection.hideDetail en controllers.xml. Debemos renombrar la acción dentro de nuestras pruebas junit.

Para migrar de OpenXava 2.0 a OpenXava 2.0.1

No hay consideraciones.

Para migrar de OpenXava 1.2.1 a OpenXava 2.0

Establece valor para referencías (en combos) con clave múltiple en las pruebas JUnit

Hasta ahora, para establecer valor a una referencía visualizada como lista-descripciones (como combo), y mapeada a la base de datos usando varias columnas, escribiamos:
PermisoConduccionKey clave = new PermisoConduccionKey();
clave.setType("C ");
clave.setLevel(1);
setValue("drivingLicence.KEY", clave.toString());
Pero, si usamos solo POJOs, sin clases 'Key', hemos de escribir:
PermisoConduccion clave = new PermisoConduccion();
clave.setType("C ");
clave.setLevel(1);
setValue("drivingLicence.KEY", clave.toString());
Es mejor usar la última forma, porque funciona con POJOs y EJBs.

Hibernate: Referencias con columnas no nula como clave foránea

En la versión EJB si tenemos una referencia a otra entidad cuya clave está compuesta por tipos primitivos, el código se genera de tal forma que no se graban nulos en la base de datos, aunque asignemos un nulo a la referencia.
En la versión Hibernate si asignamos nulo a una referencia, se graban valores nulos en la base de datos.
Por supuesto, el comportamiento de la versión Hibernate es más correcto, pero podemos hacer que en Hibernate se eviten los nulos en la base de dato, simplemente usando conversores en el mapeo de referencia (ver sección 6.3 de la guía de referencia).
Es decir, quizás necesitemos añadir algunos conversores a nuestra referencias para migrar nuestras aplicaciones de EJB2 a Hibernate.

Cambiar la sección activa

xava_activeSection ya no se usa para cambiar la sección activa. Ahora si queremos cambiar la sección activa tenemos que llamar al método setActiveSection de la vista deseada (org.openxava.view.View).

IAggragetOidCalculator

El método setContainerKey se ha renombrado a setContainer. Y su semántica también. Ahora se recibe el objeto contenedor en vez de la clave. De esta manera este calculador es consistente en la versión EJB2 y POJO (si clases para clave).

Para migrar de OpenXava 1.2 a OpenXava 1.2.1

Generación Hibernate

Ahora cuando la generación EJB se hace, la generación de código hibernate se realiza también (aunque la versión hibernate todavía no se soporta al 100%).
Aunque uses solo la versión EJB necesitas hacer una pequeña adaptación en tu proyecto:
  • Crea la carpeta hibernate en tu proyecto.
  • Crea el archivo hibernate.cfg.xml dentro de la carpeta hibernate.
El hibernate.cfg.xml ha de ser:
<!DOCTYPE hibernate-configuration PUBLIC
  "-//Hibernate/Hibernate Configuration DTD//EN"
  "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 <hibernate-configuration>
  <session-factory>
   <property
    name="hibernate.connection.datasource">@datasource.prefix@/@datasource@</property>
   <property name="hibernate.dialect">@hibernate.dialect@</property>
   <property name="hibernate.show_sql">false</property>
  </session-factory>
</hibernate-configuration>
Adicionalmente tienes que incluir la propiedad hibernate.dialect en tus archivos de configuración:
hibernate.dialect=org.hibernate.dialect.HSQLDialect

Sintaxis XML de OpenXava

  • En español PEQUEÑA pasa a ser PEQUENA. Para evitar problemas con ISO-8859-1 y UTF-8.

Para migrar de OpenXava 1.1 a OpenXava 1.2

Código generado

Ahora las interfaces remote de EJB tienen el sufijo Remote, y la interfaz de negocio generada para cada componente (por ejemplo ICliente) no contiene todos los métodos de la interface remota.
Esto es para permitir que la futura versión 2 de OpenXava pueda trabajar con EJB e Hibernate en el mismo projecto y a la vez.
Para adaptar el código hay que:
  • Borrar todo el código generado
  • Regenerar el código EJB
  • Compilar
  • Buscar y corregir los errores de sintaxis
Para corregir los errores de sintaxis se tiene que hacer cambios como éste:
Cliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
String nombre = cliente.getNombre();
Cambiarlo por:
ICliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
String nombre = cliente.getNombre();
Si se usan métodos específicos de EJB hay que moldear a la interfaz remota:
Cliente cliente = ClienteUtil.getHome().findByNombre("PEPE");
ClienteKey key = cliente.getPrimaryKey();
Cambiarlo por:
ClienteRemote cliente = ClienteUtil.getHome().findByNombre("PEPE");
[[controllers_es#toc15|mostrar un diálogo]]ClienteKey key = cliente.getPrimaryKey();
Es decir, cambiar Cliente por ICliente cuando sea posible, de no serlo cambiarlo por CustomeRemote.

Pruebas JUnit

  • Al borrar un objeto en a mantenimiento ahora OpenXava muestra una ventana javascript para confirmar, en vez de cambiar a otro controlador. Por lo tanto en tus pruebas para borrar un objeto en un módulo de mantenimiento solo necesitas usar execute("CRUD.delete"). En este caso 'Sí' como respuesta de confirmación.

Otros

  • Cambia el nombre packages-ejb.properties en gen-src-xava a packages.properties (o simplemente borrar packages-ejb.properties y regenera código).

Para migrar de OpenXava 1.0 a OpenXava 1.1

APIs

  • MetaView.getMetaViewCollection pasa a llamarse MetaView.getMetaCollectionView
  • MetaView.getMetaViewReference pasa a llamarse MetaView.getMetaReferenceView

Pruebas junit

  • Se cambia el mensaje 'Objeto borrado satisfactoriamente' por '{0} borrado satisfactoriamente'. Así es necesario cambiar los asserts de este mensaje.